package com.init.bootframe.config.aop;

import com.init.bootframe.util.TmompEncryptUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.Configuration;

/**
 * 暂未使用，加解密迁移至filter之中进行
 * AOP 切面对Controller参数处理
 */
@Configuration
@Aspect
public class ServiceAspect {
    private final String ExpGetResultDataPonit = "execution(* com.init.bootframe.*.controller.*.*(..))";
    //定义切入点,拦截servie包其子包下的所有类的所有方法
//    @Pointcut("execution(* com.haiyang.onlinejava.complier.service..*.*(..))")
    @Pointcut(ExpGetResultDataPonit)
    public void Pointcut() {

    }

    //执行方法前的拦截方法
    @Before("Pointcut()")
    public void doBeforeMethod(JoinPoint joinPoint) {
        System.out.println("我是aop前置通知，我将要执行一个方法了");
        //获取目标方法的参数信息
        Object[] obj = joinPoint.getArgs();

    }

    /**
     * 后置返回通知
     * 这里需要注意的是:
     * 如果参数中的第一个参数为JoinPoint，则第二个参数为返回值的信息
     * 如果参数中的第一个参数不为JoinPoint，则第一个参数为returning中对应的参数
     * returning 限定了只有目标方法返回值与通知方法相应参数类型时才能执行后置返回通知，否则不执行，对于returning对应的通知方法参数为Object类型将匹配任何目标返回值
     */
    @AfterReturning(value = ExpGetResultDataPonit, returning = "keys")
    public void doAfterReturningAdvice1(JoinPoint joinPoint, Object keys) {
        System.out.println("第一个后置返回通知的返回值：" + keys);
    }

    /**
     * 环绕通知：
     *   环绕通知非常强大，可以决定目标方法是否执行，什么时候执行，执行时是否需要替换方法参数，执行完毕是否需要替换返回值。
     *   环绕通知第一个参数必须是org.aspectj.lang.ProceedingJoinPoint类型
     */
    @Around(value = ExpGetResultDataPonit)
    public Object doAroundAdvice(ProceedingJoinPoint proceedingJoinPoint){
        Object obj = null;
        try {
            obj = proceedingJoinPoint.proceed();
            // 使用aop环绕通知 对返回参数进行加密
//            obj = "\"" + TmompEncryptUtil.aesEncrypt(obj.toString()) + "\"";
        } catch (Exception e) {
            e.printStackTrace();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return obj;
    }
}
